"""
消息通知系统 - 数据模型
"""
from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
from django.core.mail import send_mail
from django.conf import settings
import uuid
import json

from apps.core.models import TimeStampedModel

User = get_user_model()


class NotificationType(models.Model):
    """
    通知类型
    定义不同类型的通知模板
    """
    name = models.CharField('类型名称', max_length=100, unique=True)
    code = models.CharField('类型代码', max_length=50, unique=True)
    description = models.TextField('描述')

    # 通知渠道
    email_enabled = models.BooleanField('邮件通知', default=True)
    sms_enabled = models.BooleanField('短信通知', default=False)
    push_enabled = models.BooleanField('推送通知', default=True)
    in_app_enabled = models.BooleanField('应用内通知', default=True)

    # 模板设置
    email_template = models.TextField('邮件模板', blank=True)
    sms_template = models.TextField('短信模板', max_length=500, blank=True)
    push_template = models.TextField('推送模板', max_length=200, blank=True)
    in_app_template = models.TextField('应用内模板', max_length=500, blank=True)

    # 默认设置
    is_system_default = models.BooleanField('系统默认', default=False)
    is_active = models.BooleanField('是否启用', default=True)

    class Meta:
        db_table = 'notification_types'
        verbose_name = '通知类型'
        verbose_name_plural = '通知类型'

    def __str__(self):
        return self.name


class Notification(TimeStampedModel):
    """
    通知记录
    """
    class Priority(models.TextChoices):
        LOW = 'low', '低'
        NORMAL = 'normal', '普通'
        HIGH = 'high', '高'
        URGENT = 'urgent', '紧急'

    class Status(models.TextChoices):
        PENDING = 'pending', '待发送'
        SENDING = 'sending', '发送中'
        SENT = 'sent', '已发送'
        FAILED = 'failed', '发送失败'
        READ = 'read', '已读'
        ARCHIVED = 'archived', '已归档'

    # 基本信息
    title = models.CharField('标题', max_length=200)
    content = models.TextField('内容')
    notification_type = models.ForeignKey(
        NotificationType,
        on_delete=models.PROTECT,
        related_name='notifications',
        verbose_name='通知类型'
    )

    # 接收者
    recipient = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='received_notifications',
        verbose_name='接收者'
    )

    # 发送者（可为系统）
    sender = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        related_name='sent_notifications',
        verbose_name='发送者',
        null=True,
        blank=True
    )

    # 状态和优先级
    status = models.CharField(
        '状态',
        max_length=20,
        choices=Status.choices,
        default=Status.PENDING
    )
    priority = models.CharField(
        '优先级',
        max_length=20,
        choices=Priority.choices,
        default=Priority.NORMAL
    )

    # 发送渠道
    email_sent = models.BooleanField('邮件已发送', default=False)
    sms_sent = models.BooleanField('短信已发送', default=False)
    push_sent = models.BooleanField('推送已发送', default=False)
    in_app_sent = models.BooleanField('应用内已发送', default=False)

    # 时间信息
    scheduled_time = models.DateTimeField('计划发送时间', null=True, blank=True)
    sent_time = models.DateTimeField('实际发送时间', null=True, blank=True)
    read_time = models.DateTimeField('阅读时间', null=True, blank=True)

    # 关联对象
    content_type = models.ForeignKey(
        'contenttypes.ContentType',
        on_delete=models.CASCADE,
        null=True,
        blank=True
    )
    object_id = models.UUIDField(null=True, blank=True)
    related_object = models.GenericForeignKey('content_type', 'object_id')

    # 额外数据
    extra_data = models.JSONField('额外数据', default=dict, blank=True)
    action_url = models.URLField('操作链接', blank=True)

    # 错误信息
    error_message = models.TextField('错误信息', blank=True)
    retry_count = models.IntegerField('重试次数', default=0)

    class Meta:
        db_table = 'notifications'
        verbose_name = '通知'
        verbose_name_plural = '通知'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['recipient', 'status']),
            models.Index(fields=['notification_type']),
            models.Index(fields=['priority', 'status']),
            models.Index(fields=['scheduled_time']),
            models.Index(fields=['created_at']),
        ]

    def __str__(self):
        return f"{self.title} - {self.recipient.real_name}"

    def mark_as_read(self):
        """标记为已读"""
        if self.status != self.Status.READ:
            self.status = self.Status.READ
            self.read_time = timezone.now()
            self.save(update_fields=['status', 'read_time'])

    def send_notification(self):
        """发送通知"""
        try:
            self.status = self.Status.SENDING
            self.save(update_fields=['status'])

            # 应用内通知
            if self.notification_type.in_app_enabled:
                self.in_app_sent = True

            # 邮件通知
            if self.notification_type.email_enabled and self.recipient.email:
                self._send_email()

            # 推送通知
            if self.notification_type.push_enabled:
                self._send_push()

            self.status = self.Status.SENT
            self.sent_time = timezone.now()
            self.in_app_sent = True

        except Exception as e:
            self.status = self.Status.FAILED
            self.error_message = str(e)
            self.retry_count += 1

        self.save(update_fields=[
            'status', 'sent_time', 'email_sent', 'sms_sent',
            'push_sent', 'in_app_sent', 'error_message', 'retry_count'
        ])

    def _send_email(self):
        """发送邮件"""
        try:
            send_mail(
                subject=self.title,
                message=self.content,
                from_email=getattr(settings, 'DEFAULT_FROM_EMAIL', 'noreply@aisoes.com'),
                recipient_list=[self.recipient.email],
                fail_silently=False,
            )
            self.email_sent = True
        except Exception as e:
            raise Exception(f"邮件发送失败: {str(e)}")

    def _send_push(self):
        """发送推送通知"""
        # 这里集成推送服务（如Firebase、极光推送等）
        self.push_sent = True


class NotificationTemplate(models.Model):
    """
    通知模板
    """
    class Channel(models.TextChoices):
        EMAIL = 'email', '邮件'
        SMS = 'sms', '短信'
        PUSH = 'push', '推送'
        IN_APP = 'in_app', '应用内'

    name = models.CharField('模板名称', max_length=200)
    channel = models.CharField('通知渠道', max_length=20, choices=Channel.choices)

    # 模板内容
    subject_template = models.CharField('标题模板', max_length=200)
    body_template = models.TextField('内容模板')

    # 变量说明
    variables = models.JSONField('模板变量', default=list, help_text='模板中使用的变量列表')

    # 使用统计
    usage_count = models.IntegerField('使用次数', default=0)
    last_used = models.DateTimeField('最后使用时间', null=True, blank=True)

    class Meta:
        db_table = 'notification_templates'
        verbose_name = '通知模板'
        verbose_name_plural = '通知模板'
        unique_together = [['name', 'channel']]

    def __str__(self):
        return f"{self.name} ({self.get_channel_display()})"


class NotificationPreference(TimeStampedModel):
    """
    用户通知偏好设置
    """
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        related_name='notification_preferences',
        verbose_name='用户'
    )

    # 全局设置
    enable_notifications = models.BooleanField('启用通知', default=True)
    email_enabled = models.BooleanField('邮件通知', default=True)
    sms_enabled = models.BooleanField('短信通知', default=False)
    push_enabled = models.BooleanField('推送通知', default=True)

    # 通知类型偏好
    preferences = models.JSONField(
        '通知偏好',
        default=dict,
        help_text='各类型通知的开启状态'
    )

    # 免打扰设置
    do_not_disturb = models.BooleanField('免打扰模式', default=False)
    do_not_disturb_start = models.TimeField('免打扰开始时间', null=True, blank=True)
    do_not_disturb_end = models.TimeField('免打扰结束时间', null=True, blank=True)

    # 频率限制
    daily_limit = models.IntegerField('每日最大通知数', default=50)
    hourly_limit = models.IntegerField('每小时最大通知数', default=10)

    class Meta:
        db_table = 'notification_preferences'
        verbose_name = '通知偏好'
        verbose_name_plural = '通知偏好'

    def __str__(self):
        return f"{self.user.real_name}的通知偏好"

    def can_send_notification(self, notification_type):
        """检查是否可以发送特定类型的通知"""
        if not self.enable_notifications:
            return False

        # 检查类型偏好
        type_preference = self.preferences.get(notification_type, True)
        if not type_preference:
            return False

        # 检查免打扰时间
        if self.do_not_disturb and self._is_in_do_not_disturb_time():
            return False

        return True

    def _is_in_do_not_disturb_time(self):
        """检查是否在免打扰时间内"""
        if not (self.do_not_disturb_start and self.do_not_disturb_end):
            return False

        current_time = timezone.now().time()
        start_time = self.do_not_disturb_start
        end_time = self.do_not_disturb_end

        if start_time <= end_time:
            return start_time <= current_time <= end_time
        else:
            return current_time >= start_time or current_time <= end_time


class NotificationGroup(models.Model):
    """
    通知群组
    批量发送通知给特定用户组
    """
    name = models.CharField('群组名称', max_length=100)
    description = models.TextField('描述', blank=True)

    # 成员用户
    users = models.ManyToManyField(
        User,
        related_name='notification_groups',
        verbose_name='群组成员'
    )

    # 群组类型
    group_type = models.CharField(
        '群组类型',
        max_length=50,
        choices=[
            ('manual', '手动创建'),
            ('role_based', '基于角色'),
            ('course_based', '基于课程'),
            ('dynamic', '动态群组'),
        ],
        default='manual'
    )

    # 动态条件（用于动态群组）
    dynamic_conditions = models.JSONField(
        '动态条件',
        default=dict,
        blank=True,
        help_text='定义群组成员的条件'
    )

    class Meta:
        db_table = 'notification_groups'
        verbose_name = '通知群组'
        verbose_name_plural = '通知群组'

    def __str__(self):
        return self.name

    def get_member_count(self):
        """获取成员数量"""
        return self.users.count()

    def refresh_dynamic_members(self):
        """刷新动态群组成员"""
        if self.group_type == 'role_based':
            role = self.dynamic_conditions.get('role')
            if role:
                from django.contrib.auth import get_user_model
                User = get_user_model()
                self.users.set(User.objects.filter(role=role))

        elif self.group_type == 'course_based':
            # 基于课程的动态群组逻辑
            pass

        elif self.group_type == 'dynamic':
            # 复杂的动态条件逻辑
            pass